package com.bzframework.pro.io.manager;

import cn.hutool.core.io.FileUtil;
import com.bzframework.pro.io.configuration.CosFileProperties;
import com.bzframework.pro.io.configuration.ImageInfoEnum;
import com.bzframework.pro.io.entity.FileInfo;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.model.*;
import com.qcloud.cos.model.ciModel.persistence.OriginalInfo;
import com.qcloud.cos.model.ciModel.persistence.PicOperations;
import lombok.RequiredArgsConstructor;
import org.hswebframework.web.id.IDGenerator;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.ContentDisposition;
import org.springframework.http.MediaType;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.Objects;


/**
 * @Author bingzhong
 * @Date 2024/12/25 11:39
 * @Description
 */
@RequiredArgsConstructor
public class TencentCosFileManager implements FileManager {

    private final CosFileProperties cosFileProperties;

    private final COSClient cosClient;

    @Override
    public Mono<FileInfo> saveFile(FilePart filePart) {

        return DataBufferUtils.join(filePart.content())
                .map(dataBuffer -> {
                    // 指定文件存储桶
                    String bucketName = cosFileProperties.getBucketName();
                    String suffix = FileUtil.getSuffix(filePart.filename());
                    String random = IDGenerator.RANDOM.generate();
                    String fileName = String.format("%s-%s.%s", random, System.currentTimeMillis(), suffix);
                    String key = String.format("public/%s", fileName);
                    ObjectMetadata objectMetadata = new ObjectMetadata();
                    int contentLength = dataBuffer.readableByteCount();
                    objectMetadata.setContentLength(contentLength);
                    PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, dataBuffer.asInputStream(), objectMetadata);
                    PicOperations picOperations = new PicOperations();
                    picOperations.setIsPicInfo(cosFileProperties.getIsPicInfo());
                    putObjectRequest.setPicOperations(picOperations);
                    PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);
                    return wrapperObjectResult2FileInfo(suffix, fileName, contentLength, putObjectResult);
                });
    }

    @Override
    public Mono<Void> readFile(String fileId, ServerWebExchange exchange) {
        String bucketName = cosFileProperties.getBucketName();
        GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, fileId);
        COSObject cosObject = cosClient.getObject(getObjectRequest);
        COSObjectInputStream objectContent = cosObject.getObjectContent();

        exchange.getResponse()
                .getHeaders()
                .setContentType(MediaType.APPLICATION_OCTET_STREAM);

        //文件名
        exchange.getResponse().getHeaders().setContentDisposition(
                ContentDisposition
                        .attachment()
                        .filename(cosObject.getKey(), StandardCharsets.UTF_8)
                        .build()
        );

        return exchange.getResponse()
                .writeWith(DataBufferUtils.readInputStream(
                        () -> objectContent,
                        exchange.getResponse().bufferFactory(),
                        1024)
                );
    }

    private FileInfo wrapperObjectResult2FileInfo(String suffix, String fileName, int contentLength, PutObjectResult putObjectResult) {
        OriginalInfo originalInfo = putObjectResult.getCiUploadResult().getOriginalInfo();
        FileInfo fileInfo = new FileInfo();
        fileInfo.setId(putObjectResult.getRequestId());
        fileInfo.setFileName(fileName);
        fileInfo.setExtension(suffix);
        fileInfo.setLength(contentLength);
        fileInfo.setMd5(putObjectResult.getContentMd5());
        fileInfo.setAccessUrl(originalInfo.getLocation());
        if (Objects.equals(cosFileProperties.getIsPicInfo(), ImageInfoEnum.BACK.getStatus())) {
            fileInfo.setImageInfo(originalInfo.getImageInfo());
        }
        return fileInfo;
    }

}
